package fem2d;

import java.util.ArrayList;

import math2.MathUtilities;
import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Debugger;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshGenerator;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.Node;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticManualAnalysis;
import fem2.element.StructuralElement;
import fem2.enu.EchoLevelType;
import fem2.enu.IntegrationType;
import fem2.enu.LineSearchCriteria;
import fem2.enu.State;
import fem2.material.DruckerPragerMM;
import fem2.material.FluencyCriteria;
import fem2.material.LinearIsotropicHardeningRule;
import fem2.mesh_and_topology.SpatialCriteria;
import fem2.observer.TimeStepObserver;
import fem2.pre_and_post.HyplasMeshGenerator;
import fem2.strategies.NewtonRaphsonStrategy;
import fem2.strategies.Strategy;

public class StripFooting extends AbstractStructuralStaticDemo {

	public StripFooting() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "strip-footing.gid";
		meshFileName = "hyplas-mesh";
	}

	@Override
	public Mesh createMesh() {
		MeshGenerator mg = new HyplasMeshGenerator(
				"/home/hbui/workspace/hyplasf/Debug/data_files/08_4_3_d-p_innercone.dat");
		return mg.getMesh(2);
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();

		Constraint cx = new Constraint(false, true);
		Constraint cy = new Constraint(true, false);

		ArrayList<Node> left_nodes = MeshUtilities.seekNodesOnSurface(mesh, 1.0, 0.0, 0.0);
		ArrayList<Node> right_nodes = MeshUtilities.seekNodesOnSurface(mesh, 1.0, 0.0, -500.0);
		ArrayList<Node> bottom_nodes = MeshUtilities.seekNodesOnSurface(mesh, 0.0, 1.0, 0.0);

		mesh.addConstraint(cy, bottom_nodes);
		mesh.addConstraint(cx, left_nodes);
		mesh.addConstraint(cx, right_nodes);

		SpatialCriteria sc = new SpatialCriteria() {

			@Override
			public boolean isSatisfied(double... x) {
				boolean s = Math.abs(x[1] - 500.0) < 1e-6;
				s &= (x[0] >= 0 && x[0] <= 50);
				return s;
			}
		};
		ArrayList<Node> force_nodes = MeshUtilities.seekNodes(mesh, sc);

		Constraint cu = new Constraint(true, false);
		cu.setValue(1, -100);
		for (Node n : force_nodes) {
			n.addConstraint(cu);
		}

		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 1e7;
		double nu = 0.48;
		double thickness = 1;
		double rho = 0;
		State ss = State.PLANE_STRAIN;
		// return new StVenantKirchhoffMM(E, nu, thickness, rho, ss);

		double phi = (20.0 / 180) * Math.PI;
		double psi = phi;
		/*
		 * inner cone
		 */
		double eta = 6 * Math.sin(phi) / (Math.sqrt(3) * (3 + Math.sin(phi)));
		double xi = 6 * Math.cos(phi) / (Math.sqrt(3) * (3 + Math.sin(phi)));
		double etabar = 6 * Math.sin(psi) / (Math.sqrt(3) * (3 + Math.sin(psi)));

		double c = 490;
		double H = 0;

		FluencyCriteria hardeningLaw = new LinearIsotropicHardeningRule(c, H);

		// return new DruckerPragerMM2(E, nu, thickness, rho, ss, eta, etabar,
		// xi, hardeningLaw);
		return new DruckerPragerMM(E, nu, thickness, rho, ss, eta, etabar, xi, hardeningLaw);
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		StructuralElement e = new StructuralElement(mp, mm);
		e.setIntegrationType(IntegrationType.REDUCED_INTEGRATION);
		// e.setEchoLevel(EchoLevelType.DEBUG);
		return e;
	}

	public void run(double[] lambda) {
		Model m = createModel();

		Analysis an = new NonlinearStaticManualAnalysis(m, lambda, lambda);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1, EchoLevelType.AUX5);
		((NewtonRaphsonStrategy) s)
				.setLineSearchCriteria(LineSearchCriteria.INTERPOLATED_LINE_SEARCH);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new StripFooting();

		double[] lambda = MathUtilities.createLambdaArray(0.25e-3, 0.25e-3, 0.4e-2);
		// double[] lambda = new double[] { 0.25e-3, 0.5e-3 };

		demo.run(lambda);
	}
}
